#ifndef _MB_MASTER_APP_H
#define _MB_MASTER_APP_H

#include "sys.h"

#define USE_MASTER     1

/* ----------------------- Defines ------------------------------------------*/
#define MB_ADDRESS_BROADCAST    ( 0 )   /*! Modbus broadcast address. */
#define MB_ADDRESS_MIN          ( 1 )   /*! Smallest possible slave address. */
#define MB_ADDRESS_MAX          ( 247 ) /*! Biggest possible slave address. */
#define MB_FUNC_NONE                          (  0 )
#define MB_FUNC_READ_COILS                    (  1 )
#define MB_FUNC_READ_DISCRETE_INPUTS          (  2 )
#define MB_FUNC_WRITE_SINGLE_COIL             (  5 )
#define MB_FUNC_WRITE_MULTIPLE_COILS          ( 15 )
#define MB_FUNC_READ_HOLDING_REGISTER         (  3 )
#define MB_FUNC_READ_INPUT_REGISTER           (  4 )
#define MB_FUNC_WRITE_REGISTER                (  6 )
#define MB_FUNC_WRITE_MULTIPLE_REGISTERS      ( 16 )
#define MB_FUNC_READWRITE_MULTIPLE_REGISTERS  ( 23 )
#define MB_FUNC_DIAG_READ_EXCEPTION           (  7 )
#define MB_FUNC_DIAG_DIAGNOSTIC               (  8 )
#define MB_FUNC_DIAG_GET_COM_EVENT_CNT        ( 11 )
#define MB_FUNC_DIAG_GET_COM_EVENT_LOG        ( 12 )
#define MB_FUNC_OTHER_REPORT_SLAVEID          ( 17 )
#define MB_FUNC_ERROR                         ( 128 )

//从机
enum SLAVE_TYPE{
    BROADCAST_ADDRESS,     //广播地址
    Test_SLAVE_1,
    SLAVE_TOTOL_NUM,
};

#if USE_MASTER == 1

//主机所连接的从机数量
#define MB_MASTER_TOTAL_SLAVE_NUM   (SLAVE_TOTOL_NUM - 1)

//Modbus 数据类型
#define M_USE_DISCRETE_INPUT   (1)//离散量输入,位变量，只读
#define M_USE_COIL             (1)//线圈     ,位变量，读写
#define M_USE_REG_INPUT        (1)//输入寄存器,16-bit整型，只读
#define M_USE_REG_HOLDING      (1)//保持寄存器,16-bit整型，只读

//离散量输入
#if M_USE_DISCRETE_INPUT == 1 
#define M_DISCRETE_INPUT_START        0
#define M_DISCRETE_INPUT_NDISCRETES   64
    #if M_DISCRETE_INPUT_NDISCRETES % 8
        extern uint8_t ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES / 8 + 1];
    #else
        extern uint8_t ucMDiscInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_DISCRETE_INPUT_NDISCRETES / 8];
    #endif
#endif

//线圈
#if M_USE_COIL == 1
#define M_COIL_START 0
#define M_COIL_NCOILS 64
    #if M_COIL_NCOILS % 8
        extern uint8_t ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS / 8 + 1];
    #else
        extern uint8_t ucMCoilBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_COIL_NCOILS / 8];
    #endif
#endif

//输入寄存器
#if M_USE_REG_INPUT == 1
#define M_REG_INPUT_START 0
#define M_REG_INPUT_NREGS 100
extern uint16_t usMRegInBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_INPUT_NREGS];
#endif

//保持寄存器
#if M_USE_REG_HOLDING == 1
#define M_REG_HOLDING_START 0
#define M_REG_HOLDING_NREGS 100
extern uint16_t usMRegHoldBuf[MB_MASTER_TOTAL_SLAVE_NUM][M_REG_HOLDING_NREGS];
#endif

#define HOLD_REG_ADD_MIN        0x00
#define HOLD_REG_ADD_MAX        0x0F
#define MAX_HOLD_REG_NUM        ((HOLD_REG_ADD_MAX) - (HOLD_REG_ADD_MIN) + 1)

#define MB_MASTER_FRAME_SIZE_MIN      4

//֡帧位置
#define MB_MASTER_FRAME_ADDR         0       //地址
#define MB_MASTER_FRAME_FUNC         1       //功能码

extern void MB_M_Read_Coil_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount);
extern void MB_M_Read_DiscreteInput_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount);
extern void MB_M_Read_HoldingReg_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount);
extern void MB_M_Read_InputReg_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount);

extern void MB_M_Write_SingleCoil_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regvalue);
extern void MB_M_Write_MultipleCoils_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount,uint8_t *valuebuf);
extern void MB_M_Write_OneHoldingReg_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regvalue);
extern void MB_M_Write_MultipleHoldingReg_Frame(uint8_t slaveaddr,uint16_t regaddr,uint16_t regcount,uint16_t *valuebuf);

extern void Task_mb485_master(void* parameter);
/**
 * @brief  MB_M_ReadOneHoldBuf 从保持寄存器buf中读取一个寄存器的值
 * @param  SlaveAddr:从机地址，从1开始
 * @param  RegAddr:寄存器的起始地址,寄存器地址是从0开始
 * @retval 寄存器的值
 */
extern uint16_t MB_M_ReadOneHoldBuf(uint16_t SlaveAddr,uint16_t RegAddr);
extern void Task_mb485_master_init(void);
#endif

#endif
